home *** CD-ROM | disk | FTP | other *** search
- {$DEFINE DEBUG}
-
-
- { -----------------------------------------------------------------------------}
- { A list view control that enables access to the new style types provieded by }
- { the updated list view control. }
- { Copyright 1996, Brad Stowers. All Rights Reserved. }
- { This component can be freely used and distributed in commercial and private }
- { environments, provied this notice is not modified in any way. }
- { -----------------------------------------------------------------------------}
- { Feel free to contact me if you have any questions, comments or suggestions }
- { at bstowers@pobox.com or 72733,3374 on CompuServe. }
- { The lateset version will always be available on the web at: }
- { http://www.pobox.com/~bstowers/delphi/ }
- { -----------------------------------------------------------------------------}
- { Date last modified: October 16, 1997 }
- { -----------------------------------------------------------------------------}
-
- { -----------------------------------------------------------------------------}
- { TExtListView v3.00 Beta 8 }
- { -----------------------------------------------------------------------------}
- { }
- { Description: }
- { A list view control that enables access to the new style types provieded }
- { by the updated list view control. The updated list view is provided in }
- { the COMCTL32.DLL file that comes with Microsoft's new internet software. }
- { The version I have tested this component with is dated August 26, 1996 at }
- { 09:39. }
- { }
- { Notes: }
- { The owner drawing and column images were originally implemented by Remi }
- { Sellem (RemiS@chemware.co.uk) and Mike Lindre (no address). I only }
- { reworked them a little, integrated them into this component, and made a }
- { few changes to use the new Delphi 3 collection editor for ColumnsFormat. }
- { The original property editor (ExtColEd.pas) for this is provided for }
- { Delphi 2 users, but is not required at all for Delphi 3 usage. }
- { }
- { There are some serious limitations that I did not realize when I first }
- { released the virtual mode feature. If you are not using virtual mode }
- { (VirtualMode set to TRUE) then you need not be concerned. These problems }
- { only affect virutal mode. The problem is that since items are not stored }
- { by the list view, but rather provided as needed by an event handler, the }
- { Items property does not reflect the actual items in the list. In fact, }
- { it is always empty. Items.Count will return the proper number of items, }
- { but anything trying to use Items[x] will never get any valid data. This }
- { affects several things, such as automatic drag and drop (DragMode = }
- { dmAutomatic), the Selected property and more. This is because the }
- { implementation of TListView uses the Items property extensively. I have }
- { had some limited success in overriding the Items property and supplying }
- { my own methods for getting and setting TListItems for it, so I believe }
- { that I will eventually be able to corret this problem. However, I do not }
- { know when I will be able to get to it, so for now I suggest you not use }
- { virtual mode unless you completely understand all of the problems that }
- { may arise from it. }
- { -----------------------------------------------------------------------------}
- { }
- { Revision History: (See History.txt for full list) }
- { 3.00: Beta 1 }
- { + Initial Public Beta. }
- { + Added owner drawing. Only the vsReport mode is owner draw. Set }
- { Style to lvOwnerDrawFixed (there is no variable mode for the }
- { control) and add a handler for OnDrawItem. Also, Setting }
- { DefaultOwnerDrawing to true will provide the basic drawing for you. }
- { + Column headers can now use images from the SmallImages image list. }
- { See the ColumnsFormat property. }
- { + I'm never going to get the default sorting procedure to cover every }
- { situation that people keep coming up with, so I did the smart thing:}
- { OnSortItems event. This is fired when AutoColumnSort <> acsNoSort }
- { and an event is assigned. If not event is assigned, it sorts like }
- { it used to. The component takes care of reversing the order to }
- { account for descending when acsSortToggle is on. }
- { Beta 2 + Changed the default sorting routine so that it generates many fewer }
- { exceptions when checking for a valid date. This breaks sorting }
- { long dates (dates without a DateSeperator character in them) }
- { automatically, but that should be rare enough to warrant writing }
- { your own OnSortItems event handler for. It's very annoying when }
- { you are trying to debug to have all these exceptions being thrown }
- { around. Thanks to Allan Harkness (allan@atheroma.prestel.co.uk) for }
- { the suggestion. }
- { + Added OnSortBegin and OnSortFinished events. Bet you can guess }
- { when they get called... }
- { + Fixed nasty little column image bug. For some reason, the SECOND }
- { time you drag a header width, it toasts the bitmap. I think it has }
- { to do with the TListView class somehow resetting the column }
- { information, overwriting our information (image info). Anyway, }
- { catching the condition (begin column header drag) and resetting all }
- { the extended information for that column fixes it. See WMNotify }
- { method if you are interested. }
- { + Fixed another column image bug. Didn't always like it when image }
- { was on the right of right-aligned text. }
- { + Still have one problem, but it's only an issue if you don't know }
- { about it. Changing the alignment of a column (Columns[0].Alignment }
- { := taLeftJustify) will cause the column image to disappear. It }
- { happens because TListView wipes out our extened information. }
- { Because of that, and because the method that does it is not virtual,}
- { I can't force an update to reset the image information. I'm hoping }
- { I'll find a notification message that lets me know when something }
- { like this happens, but I can't find one so far. Anybody got any }
- { ideas? For now, you'll just have to reset it yourself if you }
- { change any Columns information by calling UpdateColumnsImages or }
- { UpdateColumnImage(Index). }
- { Beta 3 + Updated to work with Delphi 2. }
- { Beta 4 + I goofed an $IFDEF in the last beta and broke the SaveSettings }
- { property, among other things. }
- { + Date sorting didn't work for folks who use '.' character as a date }
- { sepeartor. It was being falsely identified as a valid number }
- { it could be identified as a date. Changed the order so that dates }
- { are checked for before numbers. }
- { + Changing Style back and forth between standard and owner draw would }
- { cause all sorts of nasty errors. FCanvas was being freed but not }
- { reset to NIL after. }
- { Beta 5 + Broke all stuff that was not associated with the updated COMCTL32 }
- { out into TEnhListView component. Reasoning is twofold: 1) If you }
- { don't want to have to deal with the updated DLL, you can still have }
- { some of the cool stuff like auto sorting and auto save settings, }
- { and 2) it reduces the complexity of the component, making it easier }
- { (hopefully) for me to track down some of these nasty bugs. }
- { Beta 6 + Did some more fiddling with things in an attempt to fix the nasty }
- { bug some people have related to the ExtendedStyles and/or Style }
- { and/or HideSelection properties. Is that vague enough? :) }
- { + Moved call to StoreSettings out of WM_DESTROY handler into }
- { destructor where it belongs. }
- { + Got rid of anything that even looked like it was assuming that }
- { Handle was valid. More desperation per item 1 above. }
- { + Conditionally removed all the stuff I was redeclaring when under }
- { Delphi 3. I wrote this stuff before things like LVM_GETSUBITEMRECT }
- { were declared in Borland's COMMCTRL.PAS file. No since in my }
- { redeclaring them if you don't need them. }
- { Beta 7 + Stupid oversight. Would not compile under Delphi 2. }
- { Beta 8 + OnVMFindItem event declaration was wrong. Found parameter should }
- { have been an integer: return -1 for not found, otherwise item index.}
- { + Column sizes weren't being autosaved. }
- {------------------------------------------------------------------------------}
-
-
- unit ExtListView;
-
- interface
-
- {$IFNDEF WIN32}
- ERROR! This unit only available for Delphi 2.0 or higher!!!
- {$ENDIF}
-
- uses
- Windows, Messages, Classes, Controls, ComCtrls, CommCtrl, SysUtils, Graphics,
- StdCtrls, Menus, EnhListView;
-
-
- type
- TLVDispInfo = TLVDispInfoA; // Borland forgot this one.
-
- const
- LVIF_INDENT = $0010;
- LVIF_NORECOMPUTE = $0800;
-
- {$IFNDEF VER100}
- LVCF_FMT = $0001;
- LVCF_WIDTH = $0002;
- LVCF_TEXT = $0004;
- LVCF_SUBITEM = $0008;
- {$ENDIF}
- LVCF_IMAGE = $0010;
- LVCF_ORDER = $0020;
-
- {$IFNDEF VER100}
- LVCFMT_LEFT = $0000;
- LVCFMT_RIGHT = $0001;
- LVCFMT_CENTER = $0002;
- LVCFMT_JUSTIFYMASK = $0003;
- {$ENDIF}
- LVCFMT_IMAGE = $0800; // Item displays an image from an image list.
- LVCFMT_BITMAP_ON_RIGHT = $1000; // Image appears to right of text.
- LVCFMT_COL_HAS_IMAGES = $8000; // Undocumented.
-
-
- type
- PLVItemEx = ^TLVItemEx;
- TLVItemEx = packed record
- mask: UINT;
- iItem: Integer;
- iSubItem: Integer;
- state: UINT;
- stateMask: UINT;
- pszText: PAnsiChar;
- cchTextMax: Integer;
- iImage: Integer;
- lParam: LPARAM;
- iIndent: integer;
- end;
-
- PLVDispInfoEx = ^TLVDispInfoEx;
- TLVDispInfoEx = packed record
- hdr: TNMHDR;
- item: TLVItemEx;
- end;
-
- type
- TLVColumnEx = packed record
- mask: UINT;
- fmt: Integer;
- cx: Integer;
- pszText: PAnsiChar;
- cchTextMax: Integer;
- iSubItem: Integer;
- iImage: integer; // New
- iOrder: integer; // New
- end;
-
-
- // These functions already exist, and there is no way to override them, so I'll just
- // rename them and you can use them as best you can.
- function ListView_GetColumnEx(LVWnd: HWND; iCol: Integer; var pcol: TLVColumnEx): Bool;
- function ListView_SetColumnEx(LVWnd: HWnd; iCol: Integer; const pcol: TLVColumnEx): Bool;
- function ListView_InsertColumnEx(LVWnd: HWND; iCol: Integer;
- const pcol: TLVColumnEx): Integer;
-
-
- { I think this one may work for TEnhListView, but I'm not sure. Need to check }
- const
- LVM_GETHEADER = LVM_FIRST + 31;
-
- function ListView_GetHeader(LVWnd: HWnd): HWnd;
-
- {$IFNDEF VER100}
- const
- LVM_SETICONSPACING = LVM_FIRST + 53;
-
- // -1 for cx and cy means we'll use the default (system settings)
- // 0 for cx or cy means use the current setting (allows you to change just one param)
- function ListView_SetIconSpacing(LVWnd: HWnd; cx, cy: integer): DWORD;
-
- const
- LVS_EX_GRIDLINES = $00000001; // Report mode only.
- LVS_EX_SUBITEMIMAGES = $00000002; // Report mode only.
- LVS_EX_CHECKBOXES = $00000004;
- LVS_EX_TRACKSELECT = $00000008;
- LVS_EX_HEADERDRAGDROP = $00000010; // Report mode only.
- LVS_EX_FULLROWSELECT = $00000020; // Report mode only.
- LVS_EX_ONECLICKACTIVATE = $00000040;
- LVS_EX_TWOCLICKACTIVATE = $00000080;
-
- LVM_SETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 54;
-
- function ListView_SetExtendedListViewStyle(LVWnd: HWnd; ExStyle: LPARAM): DWORD;
-
- const
- LVM_GETEXTENDEDLISTVIEWSTYLE = LVM_FIRST + 55;
-
- function ListView_GetExtendedListViewStyle(LVWnd: HWnd): DWORD;
-
- const
- LVIR_BOUNDS = 0;
- LVIR_ICON = 1;
- LVIR_LABEL = 2;
- LVIR_SELECTBOUNDS = 3;
-
- LVM_GETSUBITEMRECT = LVM_FIRST + 56;
-
- function ListView_GetSubItemRect(LVWnd: HWnd; ParentItem, SubItem, Code: integer;
- var Rect: TRect): boolean;
-
- const
- LVM_SUBITEMHITTEST = LVM_FIRST + 57;
- {$ENDIF}
-
- type
- PLVHitTestInfoEx = ^TLVHitTestInfoEx;
- TLVHitTestInfoEx = packed record
- pt: TPoint;
- flags: UINT;
- iItem: integer;
- iSubItem: integer;
- end;
-
- {$IFNDEF VER100}
- function ListView_SubItemHitTest(LVWnd: HWnd; var HitTestInfo: TLVHitTestInfoEx): integer;
-
- const
- LVM_SETCOLUMNORDERARRAY = LVM_FIRST + 58;
-
- function ListView_SetColumnOrderArray(LVWnd: HWnd; Count: integer;
- IntArray: PIntArray): boolean;
-
- const
- LVM_GETCOLUMNORDERARRAY = LVM_FIRST + 59;
-
- function ListView_GetColumnOrderArray(LVWnd: HWnd; Count: integer;
- IntArray: PIntArray): boolean;
-
- const
- LVM_SETHOTITEM = LVM_FIRST + 60;
-
- function ListView_SetHotItem(LVWnd: HWnd; Item: integer): integer;
-
- const
- LVM_GETHOTITEM = LVM_FIRST + 61;
-
- function ListView_GetHotItem(LVWnd: HWnd): integer;
-
- const
- LVM_SETHOTCURSOR = LVM_FIRST + 62;
-
- function ListView_SetHotCursor(LVWnd: HWnd; Cursor: HCursor): HCursor;
-
- const
- LVM_GETHOTCURSOR = LVM_FIRST + 63;
-
- function ListView_GetHotCursor(LVWnd: HWnd): HCursor;
-
- const
- LVM_APPROXIMATEVIEWRECT = LVM_FIRST + 64;
-
- function ListView_ApproximateViewRect(LVWnd: HWnd; Width, Height, Count: integer): DWORD;
-
- const
- LVM_SETWORKAREA = LVM_FIRST + 65;
-
- function ListView_SetWorkArea(LVWnd: HWnd; const Rect: TRect): boolean;
-
- function ListView_GetCheckState(LVWnd: HWnd; Index: UINT): boolean;
-
- procedure ListView_SetCheckState(LVWnd: HWnd; Index: UINT; Checked: boolean);
- {$ENDIF}
-
- const
- LVSICF_NOINVALIDATEALL = $00000001;
- LVSICF_NOSCROLL = $00000002;
-
- procedure ListView_SetItemCountEx(LVWnd: HWnd; Items: integer; Flags: DWORD);
-
- const
- {$IFNDEF VER100}
- { New list view style flags. }
- LVS_OWNERDATA = $1000; // Specifies a "virtual" list veiw control.
-
- { New notification messages. }
- LVN_ODCACHEHINT = LVN_FIRST-13;
- LVN_ODFINDITEMA = LVN_FIRST-52;
- LVN_ODFINDITEMW = LVN_FIRST-79;
- LVN_ODFINDITEM = LVN_ODFINDITEMA;
- {$ENDIF}
-
- LVN_ITEMACTIVATE = LVN_FIRST-14;
- LVN_ODSTATECHANGED = LVN_FIRST-15;
- LVN_MARQUEEBEGIN = LVN_FIRST-56;
-
- type
- {$IFNDEF VER100}
- PNMCacheHint = ^TNMCacheHint;
- TNMCacheHint = packed record
- hdr: TNMHDR;
- iFrom: integer;
- iTo: integer;
- end;
-
- PNMFindItem = ^TNMFindItem;
- TNMFindItem = packed record
- hdr: TNMHDR;
- iStart: integer;
- lvif: TLVFindInfo;
- end;
- {$ENDIF}
-
- PNMODStateChange = ^TNMODStateChange;
- TNMODStateChange = packed record
- hdr: TNMHDR;
- iFrom: integer;
- iTo: integer;
- uNewState: UINT;
- uOldState: UINT;
- end;
-
-
- type
- { New extended style flags converted to set format. }
- { lvxGridlines: Adds grid lines to seperate items and columns. Report mode only. }
- { lvxSubItemImages: Allows images to be displayed for subitems. Report mode only. }
- { lvxCheckboxes: Adds checkboxes to items. Checked items are stored internally as }
- { selected items. }
- { lvxTrackSelect: Tracks the mouse and highlights the item it currently positioned }
- { over by changing it's color. If mouse is left over an item for a brief period }
- { of time, it will be automatically selected. }
- { lvxHeaderDragDrop: Allows headers to be dragged to new positions and dropped, }
- { allowing users to reorder column information. }
- { lvxFullRowSelect: Allows user to click anywhere on an item to select it, }
- { highlighting the entire length of the item. Without this style, users must }
- { click inside the text of column 0. It is only useful in vsReport view style. }
- { lvxOneClickActivate: Sends an LVN_ITEMACTIVATE notification message to the parent }
- { when the user clicks an item. }
- { lvxTwoClickActivate: Sends an LVN_ITEMACTIVATE notification message to the parent }
- { when the user double clicks an item. }
- TLVExtendedStyle = (lvxGridLines, lvxSubItemImages, lvxCheckboxes, lvxTrackSelect,
- lvxHeaderDragDrop, lvxFullRowSelect, lvxOneClickActivate,
- lvxTwoClickActivate);
-
- { A set of the new style bits. }
- TLVExtendedStyles = set of TLVExtendedStyle;
-
- TLVItemCountFlag = (lvsicfNoInvalidateAll, lvsicfNoScroll);
- TLVItemCountFlags = set of TLVItemCountFlag;
-
- TLVVMMaskItem = (lvifText, lvifImage, lvifParam, lvifState, lvifIndent);
- TLVVMMaskItems = set of TLVVMMaskItem;
-
- TColumnImageAlign = (ciaLeftOfText, ciaRightOfText);
-
- TLVMarqueeBeginEvent = procedure(Sender: TObject; var CanBegin: boolean) of object;
- TLVItemActivateEvent = TNotifyEvent;
-
- TLVVMGetItemInfoEvent = procedure(Sender: TObject; Item, SubItem: integer;
- Mask: TLVVMMaskItems; var Image: integer;
- var Param: LPARAM; var State: UINT;
- var Indent: integer; var Text: string) of object;
- TLVVMCacheHintEvent = procedure(Sender: TObject; var HintInfo: TNMCacheHint) of object;
- TLVVMFindItemEvent = procedure(Sender: TObject; var FindInfo: TNMFindItem;
- var Found: integer) of object;
- TLVVMStateChangedEvent = procedure(Sender: TObject; var StateInfo: TNMODStateChange) of object;
-
- { Class for saved settings }
- TExtLVSaveSettings = class(TEnhLVSaveSettings)
- private
- FSaveColumnOrder: boolean;
- public
- constructor Create; override;
- procedure StoreColumnOrder(ColCount: integer; const IntArray: array of integer);
- procedure ReadColumnOrder(ColCount: integer; var IntArray: array of integer);
- published
- property SaveColumnOrder: boolean read FSaveColumnOrder write FSaveColumnOrder default TRUE;
- end;
-
- TExtListView = class; { forward declaration }
-
- TExtListColumn = class(TCollectionItem)
- private
- FSmallImageIndex: Integer;
- FImageAlignment : TColumnImageAlign;
- procedure DoChange;
- procedure SetSmallImageIndex(Value: Integer);
- procedure SetImageAlignment(Value: TColumnImageAlign);
- public
- constructor Create(Collection: TCollection); override;
- destructor Destroy; override;
- procedure Assign(Source: TPersistent); override;
- published
- property ImageIndex: integer
- read FSmallImageIndex write SetSmallImageIndex default -1;
- property ImageAlignment: TColumnImageAlign
- read FImageAlignment write SetImageAlignment default ciaRightOfText;
- end;
-
- TExtListColumns = class(TCollection)
- private
- FOwner: TExtListView;
- function GetItem(Index: Integer): TExtListColumn;
- procedure SetItem(Index: Integer; Value: TExtListColumn);
- protected
- function GetOwner: TPersistent; {$IFDEF VER100} override; {$ENDIF}
- procedure Update(Item: TCollectionItem); override;
- public
- constructor Create(AOwner: TExtListView);
- procedure Assign(Source: TPersistent); override;
- function Add: TExtListColumn;
- procedure Refresh;
- property Owner: TExtListView read FOwner;
- property Items[Index: Integer]: TExtListColumn read GetItem write SetItem; default;
- end;
-
- { The new class. }
- TExtListView = class(TCustomEnhListView)
- private
- FExtendedStyles: TLVExtendedStyles;
- FColumnOrder: PIntArray;
- FColumnOrderCount: integer;
- FColumnsFormat: TExtListColumns;
- FVirtualMode: boolean;
- FSaveSettings: TExtLVSaveSettings;
- FColumnsFormatChangeLink: TChangeLink;
-
- FOnMarqueeBegin: TLVMarqueeBeginEvent;
- FOnItemActivate: TLVItemActivateEvent;
- FOnVMGetItemInfo: TLVVMGetItemInfoEvent;
- FOnVMCacheHint: TLVVMCacheHintEvent;
- FOnVMFindItem: TLVVMFindItemEvent;
- FOnVMStateChanged: TLVVMStateChangedEvent;
-
- { Function to convert from our set type to expected API value. }
- function SetValueToAPIValue(Styles: TLVExtendedStyles): LPARAM;
- function SetValueFromAPIValue(Styles: DWORD): TLVExtendedStyles;
-
- procedure ColumnHeaderImagesChange(Sender: TObject);
-
- procedure CNNotify(var Message: TWMNotify); message CN_NOTIFY;
- procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
- protected
- { Property method for setting styles. }
- procedure SetExtendedStyles(Val: TLVExtendedStyles);
- function GetExtendedStyles: TLVExtendedStyles;
- function GetHeaderHandle: HWnd;
- function GetSubItemRect(Item, SubItem: integer; Index: integer): TRect;
- procedure SetHotItem(Val: integer);
- function GetHotItem: integer;
- procedure SetHotCursor(const Val: HCursor);
- function GetHotCursor: HCursor;
- procedure SetWorkArea(Rect: TRect);
- procedure SetCheckState(Index: integer; Checked: boolean);
- function GetCheckState(Index: integer): boolean;
- procedure SetVirtualMode(Val: boolean);
- procedure SetColumnsFormat(Value: TExtListColumns);
-
- procedure CreateParams(var Params: TCreateParams); override;
- procedure CreateWnd; override;
- procedure DestroyWnd; override;
- procedure Loaded; override;
- { Event method handlers -- fire the events if they exist. }
- function MarqueeBegin: boolean; virtual;
- procedure ItemActivate; virtual;
- procedure VMGetDispInfo(var ItemInfo: TLVItemEx); virtual;
- procedure VMCacheHint(var HintInfo: TNMCacheHint); virtual;
- function VMFindItem(var FindInfo: TNMFindItem): integer; virtual;
- procedure VMStateChanged(var StateInfo: TNMODStateChange); virtual;
- public
- constructor Create(AOwner: TComponent); override;
- destructor Destroy; override;
-
- { Force reset of column image information }
- procedure UpdateColumnsImages;
- procedure UpdateColumnImage(Index: integer);
-
- procedure SetIconSpacing(X, Y: integer);
- function GetSubItemAt(X, Y: integer): string;
- procedure SetColumnOrder(Count: integer; const IntArray: array of integer);
- function GetColumnOrder(Count: integer; var IntArray: array of integer): boolean;
- function ApproximateViewRect(Count: integer; const Proposed: TPoint): TPoint;
- procedure SetItemCountEx(Count: integer; Flags: TLVItemCountFlags);
- procedure StoreSettings; override;
- procedure LoadSettings; override;
-
- property HeaderHandle: HWnd
- read GetHeaderHandle;
- property SubItem_BoundsRect[Item: integer; SubItem: integer]: TRect
- index LVIR_BOUNDS
- read GetSubItemRect;
- property SubItem_IconRect[Item: integer; SubItem: integer]: TRect
- index LVIR_ICON
- read GetSubItemRect;
- property SubItem_LabelRect[Item: integer; SubItem: integer]: TRect
- index LVIR_LABEL
- read GetSubItemRect;
- property SubItem_SelectBoundsRect[Item: integer; SubItem: integer]: TRect
- index LVIR_SELECTBOUNDS
- read GetSubItemRect;
- property HotItem: integer
- read GetHotItem write SetHotItem;
- property HotCursor: HCursor
- read GetHotCursor write SetHotCursor;
- property WorkArea: TRect
- write SetWorkArea;
- property IsChecked[Index: integer]: boolean
- read GetCheckState write SetCheckState;
- published
- { I moved these to try to fix a really strange bug. Danny Crone says it works for him }
- property Columns;
- property HideSelection;
-
- { Property for new styles. }
- property ExtendedStyles: TLVExtendedStyles
- read GetExtendedStyles write SetExtendedStyles default [];
- property VirtualMode: boolean
- read FVirtualMode write SetVirtualMode default FALSE;
-
- { Autosave settings property. }
- property SaveSettings: TExtLVSaveSettings
- read FSaveSettings write FSaveSettings;
-
- property ColumnsFormat: TExtListColumns
- read FColumnsFormat write SetColumnsFormat;
-
- { Events }
- property OnMarqueeBegin: TLVMarqueeBeginEvent
- read FOnMarqueeBegin write FOnMarqueeBegin;
- property OnItemActivate: TLVItemActivateEvent
- read FOnItemActivate write FOnItemActivate;
- property OnVMGetItemInfo: TLVVMGetItemInfoEvent
- read FOnVMGetItemInfo write FOnVMGetItemInfo;
- property OnVMCacheHint: TLVVMCacheHintEvent
- read FOnVMCacheHint write FOnVMCacheHint;
- property OnVMFindItem: TLVVMFindItemEvent
- read FOnVMFindItem write FOnVMFindItem;
- property OnVMStateChanged: TLVVMStateChangedEvent
- read FOnVMStateChanged write FOnVMStateChanged;
-
- { Publish inherited protected properties }
- property AutoColumnSort;
- property AutoSortAscending;
- property CurrentSortAscending;
- property Style;
-
- property OnDrawItem;
- property OnAfterDefaultDrawItem;
- property OnSortItems;
- property OnSortBegin;
- property OnSortFinished;
-
-
- property Align;
- property BorderStyle;
- property Color;
- property ColumnClick;
- property OnClick;
- property OnDblClick;
- property Ctl3D;
- property DragMode;
- property ReadOnly default False;
- property Enabled;
- property Font;
- property IconOptions;
- property Items;
- property AllocBy;
- property MultiSelect;
- property OnChange;
- property OnChanging;
- property OnColumnClick;
- property OnCompare;
- property OnDeletion;
- property OnEdited;
- property OnEditing;
- property OnEnter;
- property OnExit;
- property OnInsert;
- property OnDragDrop;
- property OnDragOver;
- property DragCursor;
- property OnStartDrag;
- property OnEndDrag;
- property OnMouseDown;
- property OnMouseMove;
- property OnMouseUp;
- property ParentColor default False;
- property ParentFont;
- property ParentShowHint;
- property ShowHint;
- property PopupMenu;
- property ShowColumnHeaders;
- property SortType;
- property TabOrder;
- property TabStop default True;
- property ViewStyle;
- property Visible;
- property OnKeyDown;
- property OnKeyPress;
- property OnKeyUp;
- property LargeImages;
- property SmallImages;
- property StateImages;
- end;
-
-
- implementation
-
- uses
- {$IFDEF VER90}
- ExtColEd,
- {$ENDIF}
- Registry;
-
-
- function ListView_GetColumnEx(LVWnd: HWND; iCol: Integer; var pcol: TLVColumnEx): bool;
- begin
- Result := bool(SendMessage(LVWnd, LVM_GETCOLUMN, iCol, LPARAM(@pcol)));
- end;
-
- function ListView_SetColumnEx(LVWnd: HWnd; iCol: Integer; const pcol: TLVColumnEx): Bool;
- begin
- Result := bool(SendMessage(LVWnd, LVM_SETCOLUMN, iCol, Longint(@pcol)));
- end;
-
- function ListView_InsertColumnEx(LVWnd: HWND; iCol: Integer;
- const pcol: TLVColumnEx): Integer;
- begin
- Result := SendMessage(LVWnd, LVM_INSERTCOLUMN, iCol, Longint(@pcol));
- end;
-
- function ListView_GetHeader(LVWnd: HWnd): HWnd;
- begin
- Result := HWnd(SendMessage(LVWnd, LVM_GETHEADER, 0, 0));
- end;
-
- function ListView_SetIconSpacing(LVWnd: HWnd; cx, cy: integer): DWORD;
- begin
- Result := SendMessage(LVWnd, LVM_SETICONSPACING, 0, MAKELONG(cx,cy));
- end;
-
- function ListView_SetExtendedListViewStyle(LVWnd: HWnd; ExStyle: LPARAM): DWORD;
- begin
- Result := SendMessage(LVWnd, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, ExStyle);
- end;
-
- function ListView_GetExtendedListViewStyle(LVWnd: HWnd): DWORD;
- begin
- Result := SendMessage(LVWnd, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
- end;
-
- function ListView_GetSubItemRect(LVWnd: HWnd; ParentItem, SubItem, Code: integer;
- var Rect: TRect): boolean;
- begin
- Rect.Top := SubItem;
- Rect.Left := Code;
- Result := (SendMessage(LVWnd, LVM_GETSUBITEMRECT, ParentItem, LPARAM(@Rect)) <> 0);
- end;
-
- function ListView_SubItemHitTest(LVWnd: HWnd; var HitTestInfo: TLVHitTestInfoEx): integer;
- begin
- Result := SendMessage(LVWnd, LVM_SUBITEMHITTEST, 0, LPARAM(@HitTestInfo));
- end;
-
- function ListView_SetColumnOrderArray(LVWnd: HWnd; Count: integer;
- IntArray: PIntArray): boolean;
- begin
- Result := (SendMessage(LVWnd, LVM_SETCOLUMNORDERARRAY, Count, LPARAM(IntArray)) <> 0);
- end;
-
- function ListView_GetColumnOrderArray(LVWnd: HWnd; Count: integer;
- IntArray: PIntArray): boolean;
- begin
- Result := (SendMessage(LVWnd, LVM_GETCOLUMNORDERARRAY, Count, LPARAM(IntArray)) <> 0);
- end;
-
- function ListView_SetHotItem(LVWnd: HWnd; Item: integer): integer;
- begin
- Result := SendMessage(LVWnd, LVM_SETHOTITEM, Item, 0);
- end;
-
- function ListView_GetHotItem(LVWnd: HWnd): integer;
- begin
- Result := SendMessage(LVWnd, LVM_GETHOTITEM, 0, 0);
- end;
-
- function ListView_SetHotCursor(LVWnd: HWnd; Cursor: HCursor): HCursor;
- begin
- Result := HCursor(SendMessage(LVWnd, LVM_SETHOTCURSOR, 0, LPARAM(Cursor)));
- end;
-
- function ListView_GetHotCursor(LVWnd: HWnd): HCursor;
- begin
- Result := HCursor(SendMessage(LVWnd, LVM_GETHOTCURSOR, 0, 0));
- end;
-
- function ListView_ApproximateViewRect(LVWnd: HWnd; Width, Height, Count: integer): DWORD;
- begin
- Result := SendMessage(LVWnd, LVM_APPROXIMATEVIEWRECT, Count, MAKELPARAM(Width, Height));
- end;
-
- function ListView_SetWorkArea(LVWnd: HWnd; const Rect: TRect): boolean;
- begin
- Result := (SendMessage(LVWnd, LVM_SETWORKAREA, 0, LPARAM(@Rect)) <> 0);
- end;
-
- function ListView_GetCheckState(LVWnd: HWnd; Index: UINT): boolean;
- begin
- Result := (SendMessage(LVWnd, LVM_GETITEMSTATE, Index, LVIS_STATEIMAGEMASK) SHR 12)-1 <> 0;
- end;
-
- procedure ListView_SetCheckState(LVWnd: HWnd; Index: UINT; Checked: boolean);
- const
- LVIS_UNCHECKED = $1000;
- LVIS_CHECKED = $2000;
- var
- Data: integer;
- begin
- if Checked then Data := LVIS_CHECKED
- else Data := LVIS_UNCHECKED;
- ListView_SetItemState(LVWnd, Index, Data, LVIS_STATEIMAGEMASK);
- end;
-
- procedure ListView_SetItemCountEx(LVWnd: HWnd; Items: integer; Flags: DWORD);
- begin
- SendMessage(LVWnd, LVM_SETITEMCOUNT, Items, Flags);
- end;
-
-
- constructor TExtLVSaveSettings.Create;
- begin
- inherited Create;
- FSaveColumnOrder := TRUE;
- end;
-
- procedure TExtLVSaveSettings.StoreColumnOrder(ColCount: integer; const IntArray: array of integer);
- var
- Reg: TRegIniFile;
- x: integer;
- s: string;
- begin
- if ColCount < 1 then exit;
- s := '';
- for x := 0 to ColCount-1 do
- s := s + IntToStr(IntArray[x]) + ',';
- SetLength(s, Length(s)-1);
- Reg := TRegIniFile.Create(RegistryKey);
- try
- Reg.WriteString('Columns', 'Order', s);
- finally
- Reg.Free;
- end;
- end;
-
- procedure TExtLVSaveSettings.ReadColumnOrder(ColCount: integer; var IntArray: array of integer);
- var
- Reg: TRegIniFile;
- x,y: integer;
- s: string;
- begin
- if ColCount < 1 then exit;
- s := '';
- Reg := TRegIniFile.Create(RegistryKey);
- try
- s := Reg.ReadString('Columns', 'Order', '');
- finally
- Reg.Free;
- end;
- if s = '' then begin
- for x := 0 to ColCount-1 do
- IntArray[x] := x;
- exit;
- end;
- y := 0;
- for x := 0 to ColCount-1 do begin
- try
- y := Pos(',', s);
- if y = 0 then
- y := Length(s)+1;
- IntArray[x] := StrToInt(Copy(s, 1, y-1));
- except
- IntArray[x] := 0;
- end;
- s := copy(s, y+1, length(s));
- if s = '' then break;
- end;
- end;
-
-
- { Override constructor to "zero out" our internal variable. }
- constructor TExtListView.Create(AOwner: TComponent);
- begin
- inherited Create(AOwner);
- FExtendedStyles := [];
- FColumnOrder := NIL;
- FColumnOrderCount := 0;
- FSaveSettings := TExtLVSaveSettings.Create;
- FColumnsFormatChangeLink := TChangeLink.Create;
- FColumnsFormatChangeLink.OnChange := ColumnHeaderImagesChange;
- FVirtualMode := FALSE;
- FColumnsFormat := TExtListColumns.Create(Self);
- // FColumnHeaderImages := NIL;
- end;
-
- destructor TExtListView.Destroy;
- begin
- if FColumnOrder <> NIL then
- FreeMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
- FColumnsFormat.Free; { don't think i need this, it has an Owner property }
- // FColumnsFormatChangeLink.Free;
- inherited Destroy;
- { Free after inherited because inherited calls StoreSettings which uses it...}
- FSaveSettings.Free;
- end;
-
- procedure TExtListView.CreateParams(var Params: TCreateParams);
- begin
- inherited CreateParams(Params);
-
- if FVirtualMode then
- Params.Style := Params.Style or LVS_OWNERDATA;
- end;
-
- procedure TExtListView.CreateWnd;
- begin
- inherited CreateWnd;
-
- SetExtendedStyles(FExtendedStyles);
- if FColumnOrder <> NIL then
- begin
- SendMessage(Handle, LVM_SETCOLUMNORDERARRAY, FColumnOrderCount, LongInt(FColumnOrder));
- Refresh;
- end;
- end;
-
- procedure TExtListView.DestroyWnd;
- begin
- if FColumnOrder <> NIL then
- FreeMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
- FColumnOrderCount := Columns.Count;
- GetMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
- SendMessage(Handle, LVM_GETCOLUMNORDERARRAY, FColumnOrderCount,
- LPARAM(FColumnOrder));
-
- inherited DestroyWnd;
- end;
-
- procedure TExtListView.Loaded;
- begin
- inherited Loaded;
- LoadSettings;
- UpdateColumnsImages;
- end;
-
- const
- API_STYLES: array[lvxGridLines..lvxTwoClickActivate] of LPARAM = (
- LVS_EX_GRIDLINES, LVS_EX_SUBITEMIMAGES, LVS_EX_CHECKBOXES,
- LVS_EX_TRACKSELECT, LVS_EX_HEADERDRAGDROP, LVS_EX_FULLROWSELECT,
- LVS_EX_ONECLICKACTIVATE, LVS_EX_TWOCLICKACTIVATE
- );
-
- { Function to convert our style set type into the value expected by the API. }
- function TExtListView.SetValueToAPIValue(Styles: TLVExtendedStyles): LPARAM;
- var
- x: TLVExtendedStyle;
- begin
- Result := 0;
- { Check for each possible style. }
- for x := lvxGridLines to lvxTwoClickActivate do
- { If the style is set... }
- if x in Styles then
- { OR the appropriate value into the result. }
- Result := Result OR API_STYLES[x];
- end;
-
- { Function to convert from the API values to our style set type. }
- function TExtListView.SetValueFromAPIValue(Styles: DWORD): TLVExtendedStyles;
- var
- x: TLVExtendedStyle;
- begin
- Result := [];
- { Check for each possible style. }
- for x := lvxGridLines to lvxTwoClickActivate do
- { If the style is set... }
- if (API_STYLES[x] and Styles) <> 0 then
- { OR the appropriate value into the result. }
- Result := Result + [x];
- end;
-
- { Property method to get the extended style bits. }
- function TExtListView.GetExtendedStyles: TLVExtendedStyles;
- begin
- if HandleAllocated then
- FExtendedStyles := SetValueFromAPIValue(ListView_GetExtendedListViewStyle(Handle));
- Result := FExtendedStyles;
- end;
-
- { Property method to set new style bits. }
- procedure TExtListView.SetExtendedStyles(Val: TLVExtendedStyles);
- begin
- { Update the window with the new styles. }
- FExtendedStyles := Val;
- if HandleAllocated then
- ListView_SetExtendedListViewStyle(Handle, SetValueToAPIValue(Val));
- end;
-
- function TExtListView.GetHeaderHandle: HWnd;
- begin
- if HandleAllocated then
- Result := ListView_GetHeader(Handle)
- else
- Result := 0;
- end;
-
- { Not sure about how to update the view after changing this. Refresh doesn't do the job.
- Seems the best way to do it is something like:
-
- SetIconSpacing(X, Y);
- if ViewStyle = vsIcon then begin
- SendMessage(Handle, WM_SETREDRAW, 0, 0);
- try
- ViewStyle := vsSmallIcon;
- ViewStyle := vsIcon;
- finally
- SendMessage(Handle, WM_SETREDRAW, 1, 0);
- end;
- end;
-
- Does strange things if ViewStyle is not set to vsIcon!
- }
- procedure TExtListView.SetIconSpacing(X, Y: integer);
- begin
- if HandleAllocated then
- if ViewStyle = vsIcon then
- ListView_SetIconSpacing(Handle, X, Y);
- end;
-
- function TExtListView.GetSubItemRect(Item, SubItem: integer; Index: integer): TRect;
- begin
- if HandleAllocated then
- ListView_GetSubItemRect(Handle, Item, SubItem, Index, Result);
- end;
-
- function TExtListView.GetSubItemAt(X, Y: integer): string;
- var
- Info: TLVHitTestInfoEx;
- begin
- Result := '';
- if HandleAllocated then
- begin
- Info.pt := Point(X, Y);
- if ListView_SubItemHitTest(Handle, Info) <> -1 then begin
- if Info.iItem > -1 then
- if Info.iSubItem = 0 then
- Result := Items[Info.iItem].Caption
- else
- Result := Items[Info.iItem].SubItems[Info.iSubItem-1];
- end;
- end;
- end;
-
- procedure TExtListView.SetColumnOrder(Count: integer; const IntArray: array of integer);
- begin
- if FColumnOrder <> NIL then
- FreeMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
- FColumnOrderCount := Count;
- GetMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
- Move(IntArray, FColumnOrder^, FColumnOrderCount * SizeOf(Integer));
- if HandleAllocated then
- begin
- ListView_SetColumnOrderArray(Handle, Count, @IntArray);
- Refresh;
- end;
- end;
-
- function TExtListView.GetColumnOrder(Count: integer;
- var IntArray: array of integer): boolean;
- begin
- if HandleAllocated then
- begin
- if Count <> FColumnOrderCount then
- begin
- FColumnOrderCount := Count;
- if FColumnOrder <> NIL then
- FreeMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
- GetMem(FColumnOrder, FColumnOrderCount * SizeOf(Integer));
- end;
- Result := ListView_GetColumnOrderArray(Handle, FColumnOrderCount, @IntArray);
- Move(IntArray, FColumnOrder^, FColumnOrderCount * SizeOf(Integer));
- end else begin
- if FColumnOrder <> NIL then
- begin
- Move(FColumnOrder^, IntArray, Count * SizeOf(Integer));
- Result := TRUE;
- end else
- Result := FALSE;
- end;
- end;
-
- procedure TExtListView.SetHotItem(Val: integer);
- begin
- if HandleAllocated then
- ListView_SetHotItem(Handle, Val);
- end;
-
- function TExtListView.GetHotItem: integer;
- begin
- if HandleAllocated then
- Result := ListView_GetHotItem(Handle)
- else
- Result := -1;
- end;
-
- procedure TExtListView.SetHotCursor(const Val: HCursor);
- begin
- if HandleAllocated then
- ListView_SetHotCursor(Handle, Val);
- end;
-
- function TExtListView.GetHotCursor: HCursor;
- begin
- if HandleAllocated then
- Result := ListView_GetHotCursor(Handle)
- else
- Result := 0;
- end;
-
- function TExtListView.ApproximateViewRect(Count: integer; const Proposed: TPoint): TPoint;
- var
- Res: DWORD;
- begin
- if HandleAllocated then
- begin
- Res := ListView_ApproximateViewRect(Handle, Count, Proposed.X, Proposed.Y);
- Result := Point(LoWord(Res), HiWord(Res));
- end else
- Result := Point(-1, -1);
- end;
-
- procedure TExtListView.SetWorkArea(Rect: TRect);
- begin
- if HandleAllocated then
- ListView_SetWorkArea(Handle, Rect);
- end;
-
- procedure TExtListView.SetCheckState(Index: integer; Checked: boolean);
- begin
- if HandleAllocated then
- ListView_SetCheckState(Handle, Index, Checked);
- end;
-
- function TExtListView.GetCheckState(Index: integer): boolean;
- begin
- if HandleAllocated then
- Result := ListView_GetCheckState(Handle, Index)
- else
- Result := FALSE;
- end;
-
- procedure TExtListView.SetItemCountEx(Count: integer; Flags: TLVItemCountFlags);
- var
- APIFlags: DWORD;
- begin
- if HandleAllocated then
- begin
- APIFlags := 0;
- if lvsicfNoInvalidateAll in Flags then
- APIFlags := LVSICF_NOINVALIDATEALL;
- if lvsicfNoScroll in Flags then
- APIFlags := APIFlags or LVSICF_NOSCROLL;
- ListView_SetItemCountEx(Handle, Count, APIFlags);
- end;
- end;
-
- procedure TExtListView.SetVirtualMode(Val: boolean);
- var
- H: HWND;
- begin
- if Val = FVirtualMode then exit;
- FVirtualMode := Val;
- RecreateWnd;
- {$IFDEF DEBUG}
- H := Handle; { Desperate attempt to fix a nasty bug I can't reproduce }
- if H = 0 then
- raise Exception.Create('Failed to recreate window handle. Contact Brad.');
- {$ENDIF}
- end;
-
-
- procedure TExtListView.CNNotify(var Message: TWMNotify);
- begin
- with Message.NMHdr^ do begin
- Message.Result := 0;
- if FVirtualMode then begin
- case code of
- LVN_GETDISPINFO: VMGetDispInfo(PLVDispInfoEx(pointer(Message.NMHdr))^.item);
- LVN_ODCACHEHINT: VMCacheHint(PNMCacheHint(pointer(Message.NMHdr))^);
- LVN_ODSTATECHANGED: VMStateChanged(PNMODStateChange(pointer(Message.NMHdr))^);
- LVN_ODFINDITEM:
- Message.Result := VMFindItem(PNMFindItem(pointer(Message.NMHdr))^);
- else
- inherited;
- end;
- end else begin
- case code of
- LVN_ITEMACTIVATE:
- begin
- ItemActivate;
- Message.Result := 0;
- end;
- LVN_MARQUEEBEGIN:
- begin
- if MarqueeBegin then
- Message.Result := 0
- else
- Message.Result := 1;
- end;
- else
- inherited;
- end;
- end;
- end;
- end;
-
-
- procedure TExtListView.WMNotify(var Message: TWMNotify);
- begin
- inherited;
- // For some reason, the SECOND time you drag a header width, it toasts the bitmap.
- // I think it has to do with the TListView class somehow resetting the column
- // information, overwriting our information (image info). Anyway, catching the
- // condition (begin column header drag) and resetting all the extended information
- // for that column fixes it.
- if Message.NMHdr.code = HDN_BEGINTRACK then
- UpdateColumnImage(PHDNotify(Message.NMHdr).Item);
- end;
-
-
- function TExtListView.MarqueeBegin: boolean;
- begin
- Result := TRUE;
- if assigned(FOnMarqueeBegin) then
- FOnMarqueeBegin(Self, Result);
- end;
-
- procedure TExtListView.ItemActivate;
- begin
- if assigned(FOnItemActivate) then
- FOnItemActivate(Self);
- end;
-
- procedure TExtListView.VMGetDispInfo(var ItemInfo: TLVItemEx);
- function MaskFlagsToSet(Mask: UINT): TLVVMMaskItems;
- begin
- Result := [];
- if (Mask and LVIF_TEXT) = LVIF_TEXT then
- Include(Result, lvifText);
- if (Mask and LVIF_IMAGE) = LVIF_IMAGE then
- Include(Result, lvifImage);
- if (Mask and LVIF_PARAM) = LVIF_PARAM then
- Include(Result, lvifParam);
- if (Mask and LVIF_STATE) = LVIF_STATE then
- Include(Result, lvifState);
- if (Mask and LVIF_INDENT) = LVIF_INDENT then
- Include(Result, lvifIndent);
- end;
- var
- Text: string;
- NewState: integer;
- GetMask: TLVVMMaskItems;
- begin
- if ItemInfo.iItem = -1 then exit; // No way.
- Text := '';
- NewState := ItemInfo.State;
- GetMask := MaskFlagsToSet(ItemInfo.Mask);
- if assigned(FOnVMGetItemInfo) then begin
- with ItemInfo do
- FOnVMGetItemInfo(Self, iItem, iSubItem, GetMask,
- iImage, lParam, NewState, iIndent, Text);
- if (ItemInfo.mask and LVIF_TEXT) = LVIF_TEXT then
- StrLCopy(ItemInfo.pszText, PChar(Text), ItemInfo.cchTextMax);
- ItemInfo.State := NewState;
- end;
- end;
-
- procedure TExtListView.VMCacheHint(var HintInfo: TNMCacheHint);
- begin
- if assigned(FOnVMCacheHint) then
- FOnVMCacheHint(Self, HintInfo);
- end;
-
- function TExtListView.VMFindItem(var FindInfo: TNMFindItem): integer;
- begin
- Result := -1;
- if assigned(FOnVMFindItem) then
- FOnVMFindItem(Self, FindInfo, Result);
- end;
-
- procedure TExtListView.VMStateChanged(var StateInfo: TNMODStateChange);
- begin
- if assigned(FOnVMStateChanged) then
- FOnVMStateChanged(Self, StateInfo);
- end;
-
-
- procedure TExtListView.StoreSettings;
- var
- ColCount: integer;
- ColArray: PIntArray;
- begin
- with inherited SaveSettings do
- begin
- AutoSave := FSaveSettings.AutoSave;
- RegistryKey := FSaveSettings.RegistryKey;
- SaveColumnSizes := FSaveSettings.SaveColumnSizes;
- end;
-
- inherited StoreSettings;
-
- if FSaveSettings.AutoSave and (not(csDesigning in ComponentState)) then begin
- ColCount := Columns.Count;
- if FSaveSettings.SaveColumnOrder and (ColCount > 0) then begin
- GetMem(ColArray, SizeOf(Integer)*ColCount);
- try
- GetColumnOrder(ColCount, ColArray^);
- FSaveSettings.StoreColumnOrder(ColCount, ColArray^);
- finally
- FreeMem(ColArray);
- end;
- end;
- end;
- end;
-
- procedure TExtListView.LoadSettings;
- var
- ColCount: integer;
- ColArray: PIntArray;
- begin
- with inherited SaveSettings do
- begin
- AutoSave := FSaveSettings.AutoSave;
- RegistryKey := FSaveSettings.RegistryKey;
- SaveColumnSizes := FSaveSettings.SaveColumnSizes;
- end;
-
- inherited LoadSettings;
-
- if FSaveSettings.AutoSave and (not(csDesigning in ComponentState)) then begin
- ColCount := Columns.Count;
- if FSaveSettings.SaveColumnOrder and (ColCount > 0) then begin
- GetMem(ColArray, SizeOf(Integer)*ColCount);
- try
- FSaveSettings.ReadColumnOrder(ColCount, ColArray^);
- SetColumnOrder(ColCount, ColArray^);
- finally
- FreeMem(ColArray);
- end;
- end;
- end;
- end;
-
- procedure TExtListView.ColumnHeaderImagesChange(Sender: TObject);
- begin
- UpdateColumnsImages; { Images changed }
- end;
-
-
- {procedure TExtListView.SetColumnHeaderImages(Value: TImageList);
- begin
- end;}
-
- procedure TExtListView.SetColumnsFormat(Value: TExtListColumns);
- begin
- FColumnsFormat.Assign(Value);
- end;
-
- procedure TExtListView.UpdateColumnsImages;
- var
- i: Integer;
- begin
- if HandleAllocated then
- for i := 0 to Columns.Count - 1 do UpdateColumnImage(i);
- end;
-
- procedure TExtListView.UpdateColumnImage(Index: integer);
- function ValidImages: boolean;
- begin
- Result := assigned(SmallImages) and (SmallImages.Count > 0);
- end;
- var
- Column: TLVColumnEx;
- begin { UpdateColumnImage }
- if HandleAllocated and (Index > -1) and (Index < FColumnsFormat.Count) and ValidImages then
- begin
- FillChar(Column, SizeOf(Column), #0);
- ListView_GetColumnEx(Handle, Index, Column);
- with Column, FColumnsFormat[Index] do begin
- if (ImageIndex <> -1) then
- begin
- iImage := ImageIndex;
- mask := mask or LVCF_IMAGE or LVCF_FMT; // Add LVCF_FMT Just to make sure...
- fmt := fmt or LVCFMT_IMAGE;
- case Columns.Items[Index].Alignment of
- taLeftJustify: fmt := fmt or LVCFMT_LEFT;
- taCenter: fmt := fmt or LVCFMT_CENTER;
- taRightJustify: fmt := fmt or LVCFMT_RIGHT;
- end;
- if ImageAlignment = ciaRightOfText then
- fmt := fmt or LVCFMT_BITMAP_ON_RIGHT;
- end else begin
- mask := LVCF_FMT;
- fmt := fmt and not LVCFMT_IMAGE and not LVCFMT_BITMAP_ON_RIGHT;
- end;
- end;
- ListView_SetColumnEx(Handle, Index, Column);
- end;
- end;
-
-
-
- { TColumnListImage }
-
- constructor TExtListColumn.Create(Collection: TCollection);
- begin
- inherited Create(Collection);
- FSmallImageIndex := -1;
- FImageAlignment := ciaRightOfText;
- end;
-
- destructor TExtListColumn.Destroy;
- begin
- FSmallImageIndex := -1;
- FImageAlignment := ciaRightOfText;
- DoChange;
- inherited Destroy;
- end;
-
- procedure TExtListColumn.DoChange;
- var
- i: Integer;
- begin
- for i := 0 to Collection.Count-1 do
- Changed(i <> Collection.Count);
- end;
-
- procedure TExtListColumn.SetSmallImageIndex(Value: Integer);
- begin
- if FSmallImageIndex <> Value then
- begin
- FSmallImageIndex := Value;
- If FSmallImageIndex = -1 then
- FImageAlignment := ciaRightOfText;
- DoChange;
- end;
- end;
-
- procedure TExtListColumn.SetImageAlignment(Value: TColumnImageAlign);
- begin
- if FImageAlignment <> Value then
- begin
- FImageAlignment := Value;
- DoChange;
- end;
- end;
-
- procedure TExtListColumn.Assign(Source: TPersistent);
- var
- Column: TExtListColumn;
- begin
- if Source is TExtListColumn then
- begin
- Column := TExtListColumn(Source);
- ImageIndex := Column.ImageIndex;
- ImageAlignment := Column.ImageAlignment;
- end else
- inherited Assign(Source);
- end;
-
- { TListColBitMaps }
-
- constructor TExtListColumns.Create(AOwner: TExtListView);
- begin
- inherited Create(TExtListColumn);
- FOwner := AOwner;
- end;
-
- function TExtListColumns.GetItem(Index: Integer): TExtListColumn;
- begin
- Result := TExtListColumn(inherited GetItem(Index));
- end;
-
- procedure TExtListColumns.SetItem(Index: Integer; Value: TExtListColumn);
- begin
- inherited SetItem(Index, Value);
- end;
-
- function TExtListColumns.Add: TExtListColumn;
- begin
- Result := TExtListColumn(inherited Add);
- end;
-
- function TExtListColumns.GetOwner: TPersistent;
- begin
- Result := FOwner;
- end;
-
- procedure TExtListColumns.Update(Item: TCollectionItem);
- begin
- if Owner <> NIL then
- begin
- if Item <> NIL then
- Owner.UpdateColumnImage(Item.Index)
- else
- Owner.UpdateColumnsImages;
- end;
- end;
-
- procedure TExtListColumns.Refresh;
- begin
- if Owner <> NIL then
- Owner.UpdateColumnsImages;
- end;
-
- procedure TExtListColumns.Assign(Source: TPersistent);
- begin
- Clear;
- inherited Assign(Source);
- end;
-
-
- end.
-
-